package com.yeskery.nut.aop;

import com.yeskery.nut.annotation.async.Async;
import com.yeskery.nut.bean.ApplicationContext;
import com.yeskery.nut.core.ThreadPool;
import com.yeskery.nut.util.StringUtils;

import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * 异步的包装的拦截处理器
 * @author sprout
 * @version 1.0
 * 2022-08-29 17:57
 */
public class AsyncWrapInvocationHandler extends DefaultWrapInvocationHandler {

    /** 应用上下文 */
    private final ApplicationContext applicationContext;

    /**
     * 构建异步的包装的拦截处理器
     * @param proxyObjectContext 代理对象上下文
     * @param target 被代理的对象
     * @param applicationContext 应用上下文
     */
    public AsyncWrapInvocationHandler(ProxyObjectContext proxyObjectContext, Object target, ApplicationContext applicationContext) {
        super(proxyObjectContext, target);
        this.applicationContext = applicationContext;
    }

    @Override
    protected Object doInvoke(Method method, Object proxy, Object[] args) throws Exception {
        Async async = method.getAnnotation(Async.class);
        if (async == null) {
            return super.doInvoke(method, proxy, args);
        }
        ExecutorService executorService;
        String beanName = async.value();
        if (StringUtils.isEmpty(beanName)) {
            ThreadPool threadPool = applicationContext.getBean(ThreadPool.class);
            executorService = threadPool.getThreadPool();
        } else {
            executorService = applicationContext.getBean(beanName, ExecutorService.class);
        }

        Future<Object> future = executorService.submit(() -> AsyncWrapInvocationHandler.super.doInvoke(method, proxy, args));
        return Future.class.isAssignableFrom(method.getReturnType()) ? future : null;
    }
}
